using ICSharpCode.TextEditor.Document;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace ICSharpCode.TextEditor
{
	public class TextAreaMouseHandler
	{
		private TextArea textArea;
		private bool doubleclick;
		private bool clickedOnSelectedText;
		private MouseButtons button;
		private static readonly Point nilPoint = new Point(-1, -1);
		private Point mousedownpos = TextAreaMouseHandler.nilPoint;
		private Point lastmousedownpos = TextAreaMouseHandler.nilPoint;
		private bool gotmousedown;
		private bool dodragdrop;
		private TextLocation minSelection = TextLocation.Empty;
		private TextLocation maxSelection = TextLocation.Empty;
		public TextAreaMouseHandler(TextArea ttextArea)
		{
			this.textArea = ttextArea;
		}
		public void Attach()
		{
			this.textArea.Click += new EventHandler(this.TextAreaClick);
			this.textArea.MouseMove += new MouseEventHandler(this.TextAreaMouseMove);
			this.textArea.MouseDown += new MouseEventHandler(this.OnMouseDown);
			this.textArea.DoubleClick += new EventHandler(this.OnDoubleClick);
			this.textArea.MouseLeave += new EventHandler(this.OnMouseLeave);
			this.textArea.MouseUp += new MouseEventHandler(this.OnMouseUp);
			this.textArea.LostFocus += new EventHandler(this.TextAreaLostFocus);
			this.textArea.ToolTipRequest += new ToolTipRequestEventHandler(this.OnToolTipRequest);
		}
		private void OnToolTipRequest(object sender, ToolTipRequestEventArgs e)
		{
			if (e.ToolTipShown)
			{
				return;
			}
			Point mousePosition = e.MousePosition;
			FoldMarker foldMarkerFromPosition = this.textArea.TextView.GetFoldMarkerFromPosition(mousePosition.X - this.textArea.TextView.DrawingPosition.X, mousePosition.Y - this.textArea.TextView.DrawingPosition.Y);
			if (foldMarkerFromPosition != null && foldMarkerFromPosition.IsFolded)
			{
				StringBuilder stringBuilder = new StringBuilder(foldMarkerFromPosition.InnerText);
				int num = 0;
				for (int i = 0; i < stringBuilder.Length; i++)
				{
					if (stringBuilder[i] == '\n')
					{
						num++;
						if (num >= 10)
						{
							stringBuilder.Remove(i + 1, stringBuilder.Length - i - 1);
							stringBuilder.Append(Environment.NewLine);
							stringBuilder.Append("...");
							break;
						}
					}
				}
				stringBuilder.Replace("\t", "    ");
				e.ShowToolTip(stringBuilder.ToString());
				return;
			}
			List<TextMarker> markers = this.textArea.Document.MarkerStrategy.GetMarkers(e.LogicalPosition);
			foreach (TextMarker current in markers)
			{
				if (current.ToolTip != null)
				{
					e.ShowToolTip(current.ToolTip.Replace("\t", "    "));
					break;
				}
			}
		}
		private void ShowHiddenCursorIfMovedOrLeft()
		{
			this.textArea.ShowHiddenCursor(!this.textArea.Focused || !this.textArea.ClientRectangle.Contains(this.textArea.PointToClient(Cursor.Position)));
		}
		private void TextAreaLostFocus(object sender, EventArgs e)
		{
			this.textArea.BeginInvoke(new MethodInvoker(this.ShowHiddenCursorIfMovedOrLeft));
		}
		private void OnMouseLeave(object sender, EventArgs e)
		{
			this.ShowHiddenCursorIfMovedOrLeft();
			this.gotmousedown = false;
			this.mousedownpos = TextAreaMouseHandler.nilPoint;
		}
		private void OnMouseUp(object sender, MouseEventArgs e)
		{
			this.textArea.SelectionManager.selectFrom.where = 0;
			this.gotmousedown = false;
			this.mousedownpos = TextAreaMouseHandler.nilPoint;
		}
		private void TextAreaClick(object sender, EventArgs e)
		{
			Point mousepos = this.textArea.mousepos;
			if (this.dodragdrop)
			{
				return;
			}
			if (this.clickedOnSelectedText && this.textArea.TextView.DrawingPosition.Contains(mousepos.X, mousepos.Y))
			{
				this.textArea.SelectionManager.ClearSelection();
				TextLocation logicalPosition = this.textArea.TextView.GetLogicalPosition(mousepos.X - this.textArea.TextView.DrawingPosition.X, mousepos.Y - this.textArea.TextView.DrawingPosition.Y);
				this.textArea.Caret.Position = logicalPosition;
				this.textArea.SetDesiredColumn();
			}
		}
		private void TextAreaMouseMove(object sender, MouseEventArgs e)
		{
			this.textArea.mousepos = e.Location;
			switch (this.textArea.SelectionManager.selectFrom.where)
			{
				case 1:
				{
					this.ExtendSelectionToMouse();
					return;
				}
			}
			this.textArea.ShowHiddenCursor(false);
			if (this.dodragdrop)
			{
				this.dodragdrop = false;
				return;
			}
			this.doubleclick = false;
			this.textArea.mousepos = new Point(e.X, e.Y);
			if (this.clickedOnSelectedText)
			{
				if (Math.Abs(this.mousedownpos.X - e.X) >= SystemInformation.DragSize.Width / 2 || Math.Abs(this.mousedownpos.Y - e.Y) >= SystemInformation.DragSize.Height / 2)
				{
					this.clickedOnSelectedText = false;
					ISelection selectionAt = this.textArea.SelectionManager.GetSelectionAt(this.textArea.Caret.Offset);
					if (selectionAt != null)
					{
						string selectedText = selectionAt.SelectedText;
						bool flag = SelectionManager.SelectionIsReadOnly(this.textArea.Document, selectionAt);
						if (selectedText != null && selectedText.Length > 0)
						{
							DataObject dataObject = new DataObject();
							dataObject.SetData(DataFormats.UnicodeText, true, selectedText);
							dataObject.SetData(selectionAt);
							this.dodragdrop = true;
							this.textArea.DoDragDrop(dataObject, flag ? (DragDropEffects.Copy | DragDropEffects.Scroll) : DragDropEffects.All);
						}
					}
				}
				return;
			}
			if (e.Button == MouseButtons.Left && this.gotmousedown && this.textArea.SelectionManager.selectFrom.where == 2)
			{
				this.ExtendSelectionToMouse();
			}
		}
		private void ExtendSelectionToMouse()
		{
			Point mousepos = this.textArea.mousepos;
			TextLocation textLocation = this.textArea.TextView.GetLogicalPosition(Math.Max(0, mousepos.X - this.textArea.TextView.DrawingPosition.X), mousepos.Y - this.textArea.TextView.DrawingPosition.Y);
			int arg_6C_0 = textLocation.Y;
			textLocation = this.textArea.Caret.ValidatePosition(textLocation);
			TextLocation position = this.textArea.Caret.Position;
			if (position == textLocation && this.textArea.SelectionManager.selectFrom.where != 1)
			{
				return;
			}
			if (this.textArea.SelectionManager.selectFrom.where == 1)
			{
				if (textLocation.Y < this.textArea.SelectionManager.SelectionStart.Y)
				{
					this.textArea.Caret.Position = new TextLocation(0, textLocation.Y);
				}
				else
				{
					this.textArea.Caret.Position = this.textArea.SelectionManager.NextValidPosition(textLocation.Y);
				}
			}
			else
			{
				this.textArea.Caret.Position = textLocation;
			}
			if (!this.minSelection.IsEmpty && this.textArea.SelectionManager.SelectionCollection.Count > 0 && this.textArea.SelectionManager.selectFrom.where == 2)
			{
				ISelection arg_1A1_0 = this.textArea.SelectionManager.SelectionCollection[0];
				TextLocation textLocation2 = this.textArea.SelectionManager.GreaterEqPos(this.minSelection, this.maxSelection) ? this.maxSelection : this.minSelection;
				TextLocation textLocation3 = this.textArea.SelectionManager.GreaterEqPos(this.minSelection, this.maxSelection) ? this.minSelection : this.maxSelection;
				if (this.textArea.SelectionManager.GreaterEqPos(textLocation3, textLocation) && this.textArea.SelectionManager.GreaterEqPos(textLocation, textLocation2))
				{
					this.textArea.SelectionManager.SetSelection(textLocation2, textLocation3);
				}
				else
				{
					if (this.textArea.SelectionManager.GreaterEqPos(textLocation3, textLocation))
					{
						int offset = this.textArea.Document.PositionToOffset(textLocation);
						textLocation2 = this.textArea.Document.OffsetToPosition(this.FindWordStart(this.textArea.Document, offset));
						this.textArea.SelectionManager.SetSelection(textLocation2, textLocation3);
					}
					else
					{
						int offset2 = this.textArea.Document.PositionToOffset(textLocation);
						textLocation3 = this.textArea.Document.OffsetToPosition(this.FindWordEnd(this.textArea.Document, offset2));
						this.textArea.SelectionManager.SetSelection(textLocation2, textLocation3);
					}
				}
			}
			else
			{
				this.textArea.SelectionManager.ExtendSelection(position, this.textArea.Caret.Position);
			}
			this.textArea.SetDesiredColumn();
		}
		private void DoubleClickSelectionExtend()
		{
			Point mousepos = this.textArea.mousepos;
			this.textArea.SelectionManager.ClearSelection();
			if (this.textArea.TextView.DrawingPosition.Contains(mousepos.X, mousepos.Y))
			{
				FoldMarker foldMarkerFromPosition = this.textArea.TextView.GetFoldMarkerFromPosition(mousepos.X - this.textArea.TextView.DrawingPosition.X, mousepos.Y - this.textArea.TextView.DrawingPosition.Y);
				if (foldMarkerFromPosition != null && foldMarkerFromPosition.IsFolded)
				{
					foldMarkerFromPosition.IsFolded = false;
					this.textArea.MotherTextAreaControl.AdjustScrollBars();
				}
				if (this.textArea.Caret.Offset < this.textArea.Document.TextLength)
				{
					char charAt = this.textArea.Document.GetCharAt(this.textArea.Caret.Offset);
					if (charAt == '"')
					{
						if (this.textArea.Caret.Offset < this.textArea.Document.TextLength)
						{
							int num = this.FindNext(this.textArea.Document, this.textArea.Caret.Offset + 1, '"');
							this.minSelection = this.textArea.Caret.Position;
							if (num > this.textArea.Caret.Offset && num < this.textArea.Document.TextLength)
							{
								num++;
							}
							this.maxSelection = this.textArea.Document.OffsetToPosition(num);
						}
					}
					else
					{
						this.minSelection = this.textArea.Document.OffsetToPosition(this.FindWordStart(this.textArea.Document, this.textArea.Caret.Offset));
						this.maxSelection = this.textArea.Document.OffsetToPosition(this.FindWordEnd(this.textArea.Document, this.textArea.Caret.Offset));
					}
					this.textArea.Caret.Position = this.maxSelection;
					this.textArea.SelectionManager.ExtendSelection(this.minSelection, this.maxSelection);
				}
				if (this.textArea.SelectionManager.selectionCollection.Count > 0)
				{
					ISelection selection = this.textArea.SelectionManager.selectionCollection[0];
					selection.StartPosition = this.minSelection;
					selection.EndPosition = this.maxSelection;
					this.textArea.SelectionManager.SelectionStart = this.minSelection;
				}
				this.textArea.SetDesiredColumn();
				this.textArea.Refresh();
			}
		}
		private void OnMouseDown(object sender, MouseEventArgs e)
		{
			this.textArea.mousepos = e.Location;
			Point location = e.Location;
			if (this.dodragdrop)
			{
				return;
			}
			if (this.doubleclick)
			{
				this.doubleclick = false;
				return;
			}
			if (this.textArea.TextView.DrawingPosition.Contains(location.X, location.Y))
			{
				this.gotmousedown = true;
				this.textArea.SelectionManager.selectFrom.where = 2;
				this.button = e.Button;
				if (this.button == MouseButtons.Left && e.Clicks == 2)
				{
					int num = Math.Abs(this.lastmousedownpos.X - e.X);
					int num2 = Math.Abs(this.lastmousedownpos.Y - e.Y);
					if (num <= SystemInformation.DoubleClickSize.Width && num2 <= SystemInformation.DoubleClickSize.Height)
					{
						this.DoubleClickSelectionExtend();
						this.lastmousedownpos = new Point(e.X, e.Y);
						if (this.textArea.SelectionManager.selectFrom.where == 1 && !this.minSelection.IsEmpty && !this.maxSelection.IsEmpty && this.textArea.SelectionManager.SelectionCollection.Count > 0)
						{
							this.textArea.SelectionManager.SelectionCollection[0].StartPosition = this.minSelection;
							this.textArea.SelectionManager.SelectionCollection[0].EndPosition = this.maxSelection;
							this.textArea.SelectionManager.SelectionStart = this.minSelection;
							this.minSelection = TextLocation.Empty;
							this.maxSelection = TextLocation.Empty;
						}
						return;
					}
				}
				this.minSelection = TextLocation.Empty;
				this.maxSelection = TextLocation.Empty;
				this.lastmousedownpos = (this.mousedownpos = new Point(e.X, e.Y));
				if (this.button == MouseButtons.Left)
				{
					FoldMarker foldMarkerFromPosition = this.textArea.TextView.GetFoldMarkerFromPosition(location.X - this.textArea.TextView.DrawingPosition.X, location.Y - this.textArea.TextView.DrawingPosition.Y);
					if (foldMarkerFromPosition != null && foldMarkerFromPosition.IsFolded)
					{
						if (this.textArea.SelectionManager.HasSomethingSelected)
						{
							this.clickedOnSelectedText = true;
						}
						TextLocation textLocation = new TextLocation(foldMarkerFromPosition.StartColumn, foldMarkerFromPosition.StartLine);
						TextLocation endPosition = new TextLocation(foldMarkerFromPosition.EndColumn, foldMarkerFromPosition.EndLine);
						this.textArea.SelectionManager.SetSelection(new DefaultSelection(this.textArea.TextView.Document, textLocation, endPosition));
						this.textArea.Caret.Position = textLocation;
						this.textArea.SetDesiredColumn();
						this.textArea.Focus();
						return;
					}
					if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift)
					{
						this.ExtendSelectionToMouse();
					}
					else
					{
						TextLocation logicalPosition = this.textArea.TextView.GetLogicalPosition(location.X - this.textArea.TextView.DrawingPosition.X, location.Y - this.textArea.TextView.DrawingPosition.Y);
						this.clickedOnSelectedText = false;
						int offset = this.textArea.Document.PositionToOffset(logicalPosition);
						if (this.textArea.SelectionManager.HasSomethingSelected && this.textArea.SelectionManager.IsSelected(offset))
						{
							this.clickedOnSelectedText = true;
						}
						else
						{
							this.textArea.SelectionManager.ClearSelection();
							if (location.Y > 0 && location.Y < this.textArea.TextView.DrawingPosition.Height)
							{
								TextLocation position = default(TextLocation);
								position.Y = Math.Min(this.textArea.Document.TotalNumberOfLines - 1, logicalPosition.Y);
								position.X = logicalPosition.X;
								this.textArea.Caret.Position = position;
								this.textArea.SetDesiredColumn();
							}
						}
					}
				}
				else
				{
					if (this.button == MouseButtons.Right)
					{
						TextLocation logicalPosition2 = this.textArea.TextView.GetLogicalPosition(location.X - this.textArea.TextView.DrawingPosition.X, location.Y - this.textArea.TextView.DrawingPosition.Y);
						int offset2 = this.textArea.Document.PositionToOffset(logicalPosition2);
						if (!this.textArea.SelectionManager.HasSomethingSelected || !this.textArea.SelectionManager.IsSelected(offset2))
						{
							this.textArea.SelectionManager.ClearSelection();
							if (location.Y > 0 && location.Y < this.textArea.TextView.DrawingPosition.Height)
							{
								TextLocation position2 = default(TextLocation);
								position2.Y = Math.Min(this.textArea.Document.TotalNumberOfLines - 1, logicalPosition2.Y);
								position2.X = logicalPosition2.X;
								this.textArea.Caret.Position = position2;
								this.textArea.SetDesiredColumn();
							}
						}
					}
				}
			}
			this.textArea.Focus();
		}
		private int FindNext(IDocument document, int offset, char ch)
		{
			LineSegment lineSegmentForOffset = document.GetLineSegmentForOffset(offset);
			int num = lineSegmentForOffset.Offset + lineSegmentForOffset.Length;
			while (offset < num && document.GetCharAt(offset) != ch)
			{
				offset++;
			}
			return offset;
		}
		private bool IsSelectableChar(char ch)
		{
			return char.IsLetterOrDigit(ch) || ch == '_';
		}
		private int FindWordStart(IDocument document, int offset)
		{
			LineSegment lineSegmentForOffset = document.GetLineSegmentForOffset(offset);
			if (offset > 0 && char.IsWhiteSpace(document.GetCharAt(offset - 1)) && char.IsWhiteSpace(document.GetCharAt(offset)))
			{
				while (offset > lineSegmentForOffset.Offset)
				{
					if (!char.IsWhiteSpace(document.GetCharAt(offset - 1)))
					{
						break;
					}
					offset--;
				}
			}
			else
			{
				if (!this.IsSelectableChar(document.GetCharAt(offset)))
				{
					if (offset <= 0 || !char.IsWhiteSpace(document.GetCharAt(offset)) || !this.IsSelectableChar(document.GetCharAt(offset - 1)))
					{
						if (offset > 0 && !char.IsWhiteSpace(document.GetCharAt(offset - 1)) && !this.IsSelectableChar(document.GetCharAt(offset - 1)))
						{
							return Math.Max(0, offset - 1);
						}
						return offset;
					}
				}
				while (offset > lineSegmentForOffset.Offset)
				{
					if (!this.IsSelectableChar(document.GetCharAt(offset - 1)))
					{
						break;
					}
					offset--;
				}
			}
			return offset;
		}
		private int FindWordEnd(IDocument document, int offset)
		{
			LineSegment lineSegmentForOffset = document.GetLineSegmentForOffset(offset);
			if (lineSegmentForOffset.Length == 0)
			{
				return offset;
			}
			int num = lineSegmentForOffset.Offset + lineSegmentForOffset.Length;
			offset = Math.Min(offset, num - 1);
			if (this.IsSelectableChar(document.GetCharAt(offset)))
			{
				while (offset < num)
				{
					if (!this.IsSelectableChar(document.GetCharAt(offset)))
					{
						break;
					}
					offset++;
				}
			}
			else
			{
				if (!char.IsWhiteSpace(document.GetCharAt(offset)))
				{
					return Math.Max(0, offset + 1);
				}
				if (offset > 0 && char.IsWhiteSpace(document.GetCharAt(offset - 1)))
				{
					while (offset < num)
					{
						if (!char.IsWhiteSpace(document.GetCharAt(offset)))
						{
							break;
						}
						offset++;
					}
				}
			}
			return offset;
		}
		private void OnDoubleClick(object sender, EventArgs e)
		{
			if (this.dodragdrop)
			{
				return;
			}
			this.textArea.SelectionManager.selectFrom.where = 2;
			this.doubleclick = true;
		}
	}
}
